package io.yyxx.boot.business.service.impl;

import cn.hutool.json.JSONUtil;
import io.yyxx.boot.business.entity.billDataEntity.HotelBillData;
import io.yyxx.boot.business.vo.HotelBillResponseVo;
import io.yyxx.boot.util.DateTimeToTimestampUtil;
import io.yyxx.boot.util.SaveDataToYiDa;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class Hotel {
    @Resource
    private SaveDataToYiDa saveDataToYiDa;

    @Resource
    private HotelBillDataServiceImpl hotelBillDataServiceImpl;

    public void saveHotelBillToYiDa() {
        List<HotelBillResponseVo> responseVoToYiDa;
        //分别从数据库中查询酒店账单数据
        List<HotelBillData> hotelBillData = hotelBillDataServiceImpl.selectHotelBillData();

        // 将筛选后的数据映射到 ResponseVo 对象中，并拼接时间字符串
        responseVoToYiDa = hotelBillData.stream()
                .map(data -> {
                    HotelBillResponseVo vo = new HotelBillResponseVo();
                    ArrayList<String> travelerId = new ArrayList<>();
                    ArrayList<String> dept = new ArrayList<>();
                    ArrayList<String> time = new ArrayList<>();

                    travelerId.add(data.getTravelerId());
                    dept.add(data.getDepartmentId());

                    //将时间转为时间戳
                    String startTimestamp = DateTimeToTimestampUtil.DateTimeToTimestamp2(data.getCheckInDate()) + "";
                    String endTimestamp = DateTimeToTimestampUtil.DateTimeToTimestamp2(data.getCheckoutDate()) + "";
                    time.add(startTimestamp);
                    time.add(endTimestamp);

                    vo.setTravelerId(travelerId);                    //  出差人id
                    vo.setPaymentDepartmentId(dept);                  // 费用部门id
                    vo.setHotelSettlementFee(data.getSettlementFee());    // 酒店结算
                    String bookTime = DateTimeToTimestampUtil.DateTimeToTimestamp2(data.getBookTime()) + "";
                    vo.setBookTime(bookTime);                     // 预订时间
                    vo.setProjectName(data.getProjectName());   // 项目名称
                    vo.setProjectCode(data.getProjectCode());   // 项目编码
                    vo.setApplyId(data.getApplyId());           // 审批单号

                    vo.setTime(time);                            //  时间区间
                    vo.setHotelName(data.getHotelName());          // 酒店名称
                    vo.setCity(data.getCity());                     // 酒店城市
                    vo.setState("未报销");                        //设置状态
                    vo.setCostCenter(data.getCostCenter());    // 成本中心
                    vo.setCostCenterNumber(data.getCostCenterNumber());// 成本中心编码

                    vo.setFeeTypeDesc(data.getFeeTypeDesc());// 费用类型描述
                    vo.setSettleTypeDesc(data.getSettleTypeDesc());//结算类型描述
                    return vo;
                })
                .collect(Collectors.toList());

// ========== 新增：酒店账单筛选与合并功能开始 ==========
// 1. 筛选掉结算类型为"个人现付"的记录
        List<HotelBillResponseVo> filteredData = responseVoToYiDa.stream()
                .filter(vo -> !"个人现付".equals(vo.getSettleTypeDesc()))
                .collect(Collectors.toList());

// 2. 按费用类型分组："酒店预订"一组，其他一组
// 2.1 "酒店预订"组（主组）
        List<HotelBillResponseVo> hotelBookingGroup = filteredData.stream()
                .filter(vo -> "酒店预订".equals(vo.getFeeTypeDesc()))
                .collect(Collectors.toList());

// 2.2 非"酒店预订"组（其他组）
        List<HotelBillResponseVo> otherGroup = filteredData.stream()
                .filter(vo -> !"酒店预订".equals(vo.getFeeTypeDesc()))
                .collect(Collectors.toList());

// 3. 处理其他组：按city和travelerId分组并计算总和（关键修改：分组条件调整）
        Map<String, Double> otherCityTravelerSumMap = otherGroup.stream()
                // 过滤掉city或travelerId为空的记录（避免空键）
                .filter(vo ->
                        vo.getCity() != null && !vo.getCity().trim().isEmpty() &&
                                vo.getTravelerId() != null && !vo.getTravelerId().isEmpty()
                )
                // 按city和travelerId组合作为键分组，计算总和
                .collect(Collectors.groupingBy(
                        vo -> vo.getCity() + "|" + vo.getTravelerId().get(0), // 组合键：city|travelerId
                        Collectors.summingDouble(HotelBillResponseVo::getHotelSettlementFee)
                ));

// 4. 合并逻辑1：将其他组的总和匹配到主组对应city和travelerId的记录中（关键修改：匹配条件调整）
        Set<String> matchedKeys = new HashSet<>(); // 记录已匹配的组合键
        for (HotelBillResponseVo mainVo : hotelBookingGroup) {
            String mainCity = mainVo.getCity();
            List<String> mainTravelerIds = mainVo.getTravelerId();

            // 检查必要条件
            if (mainCity == null || mainTravelerIds == null || mainTravelerIds.isEmpty()) {
                continue;
            }

            String mainKey = mainCity + "|" + mainTravelerIds.get(0); // 组合键：city|travelerId

            // 若主组记录的city和travelerId在其他组有匹配，设置serviceFee
            if (otherCityTravelerSumMap.containsKey(mainKey)) {
                double matchedSum = otherCityTravelerSumMap.get(mainKey);
                mainVo.setServiceFee(String.valueOf(matchedSum));
                // 记录已匹配的组合键
                matchedKeys.add(mainKey);
            }
        }

// 5. 处理其他组中未匹配到主组的记录（关键修改：过滤条件调整）
        List<HotelBillResponseVo> unmatchedOtherList = otherGroup.stream()
                .filter(vo -> {
                    String city = vo.getCity();
                    List<String> travelerIds = vo.getTravelerId();

                    // 若city或travelerId为空，直接保留
                    if (city == null || travelerIds == null || travelerIds.isEmpty()) {
                        return true;
                    }

                    String key = city + "|" + travelerIds.get(0);
                    // 未匹配的条件：组合键不在已匹配的key列表中
                    return !matchedKeys.contains(key);
                })
                .peek(vo -> {
                    // 未匹配的记录：serviceFee设为自身settlementFee，settlementFee设为0
                    vo.setServiceFee(String.valueOf(vo.getHotelSettlementFee()));
                    vo.setHotelSettlementFee(0.0);
                })
                .collect(Collectors.toList());

// 6. 合并最终结果：主组（已更新serviceFee） + 其他组未匹配的记录
        List<HotelBillResponseVo> finalResult = new ArrayList<>();
        finalResult.addAll(hotelBookingGroup);         // 添加"酒店预订"组（已合并匹配的费用）
        finalResult.addAll(unmatchedOtherList);        // 添加其他组未匹配的记录

// 7. 用最终结果替换原responseVoToYiDa
        responseVoToYiDa = finalResult;
// ========== 新增：酒店账单筛选与合并功能结束 ==========

        //调用SendData发送至宜搭
        for (HotelBillResponseVo hltelBillResponseVo : responseVoToYiDa) {
            //转成josn格式
            String jsonStr = JSONUtil.toJsonStr(hltelBillResponseVo);
            //调用SendData发送至宜搭
            try {
                saveDataToYiDa.saveData(jsonStr);
                log.info("酒店账单数据jsonStr:" + jsonStr);
                log.info("酒店账单数据发送成功");
            } catch (Exception e) {
                log.error("酒店账单数据向宜搭发送失败" + e);
                throw new RuntimeException(e);
            }
        }
    }
}
